package com.wiz.web.service.impl;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;
import javax.imageio.ImageIO;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.NameValuePair;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.google.gson.reflect.TypeToken;
import com.wiz.common.Constant;
import com.wiz.common.util.ByteUtil;
import com.wiz.common.util.DecimalUtil;
import com.wiz.common.util.MD5;
import com.wiz.common.util.QRCodeUtil;
import com.wiz.web.dao.mapper.HqStationMapper;
import com.wiz.web.dao.mapper.MemberMapper;
import com.wiz.web.manager.HttpManager;
import com.wiz.web.manager.SMSManager;
import com.wiz.web.manager.WxManager;
import com.wiz.web.manager.WxRemoteManager;
import com.wiz.web.service.AccountService;
import com.wiz.web.service.MemberService;
import com.wiz.web.vo.criteria.AccountAmountHistoryCriteria;
import com.wiz.web.vo.criteria.AccountChargeHistoryCriteria;
import com.wiz.web.vo.criteria.AccountPointHistoryCriteria;
import com.wiz.web.vo.criteria.MemberCriteria;
import com.wiz.web.vo.to.AccountAmountHistoryTO;
import com.wiz.web.vo.to.AccountChargeHistoryTO;
import com.wiz.web.vo.to.AccountPointHistoryTO;
import com.wiz.web.vo.to.MemberGradeTO;
import com.wiz.web.vo.to.MemberTO;
import com.wiz.web.vo.to.PRConfigTO;
import com.wiz.web.vo.to.PageTO;
import com.wiz.web.vo.to.ResultTO;
import com.wiz.web.vo.type.CompanyType;
import com.wiz.web.vo.type.MemberStatusType;

@Service("memberService")
public class MemberServiceImpl extends BasicServiceImpl implements MemberService,Constant {
	private transient final Logger log = LoggerFactory.getLogger(getClass());
	
	@Resource
	private MemberMapper memberMapper;
	@Resource
	private HqStationMapper hqStationMapper;
	@Resource
	private AccountService accountService;
	@Resource
	private HttpManager httpManager;
	@Resource
	private WxManager wxManager;
	@Resource
	private WxRemoteManager wxRemoteManager;
	@Resource
	private SMSManager smsManager;
	
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.DEFAULT)
	public String getMemberInfo(MemberCriteria criteria) {
		MemberTO memberTO = memberMapper.getMemberInfo(criteria);
		if(memberTO == null){
			return RESPONSE_CODE_INVALID_MEMBER;
		}
		memberTO.toPRList();
		if(criteria.getPrId() != null && criteria.getPrId() > 0){
			PRConfigTO prTO = hqStationMapper.getPrConfig(criteria.getPrId());
			if(prTO != null){
				if(prTO.getOilType() == 2){//柴油优惠
					memberTO.setUseSaleAmount(memberTO.getDieselSaleAmount());
					memberTO.setUsePoint(memberTO.getDieselPoint());
				}else{
					memberTO.setUseSaleAmount(memberTO.getSaleAmount());
					memberTO.setUsePoint(memberTO.getPoint());
				}
			}
		}
		return returnResult(CODE_OK,STRING_OK,memberTO);
	}
	
	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.DEFAULT)
	public String getMembersByFuzzyQuery(MemberCriteria criteria) {
		List<MemberTO> list = memberMapper.getMembersByFuzzyQuery(criteria);
		for(MemberTO memberTO:list){
			memberTO.toPRList();
		}
		PageTO page = new PageTO();
		page.setPageNo(criteria.getPageNo());
		page.setPageSize(criteria.getPageSize());
		if(criteria.getPageSize()!=null){
			int total = memberMapper.getCntMembersByFuzzyQuery(criteria);
			page.setPageCount(totalPage(total,criteria.getPageSize()));
			page.setTotal(total);
		}
		page.setDataList(list);
		return returnResult(CODE_OK, STRING_OK, page);
	}

	@Override
	public String getGradeByMemberId(MemberCriteria criteria) {
		MemberGradeTO to = memberMapper.getGradeByMemberId(criteria);
		return returnResult(CODE_OK,STRING_OK,to);
	}
	
	@Override
	public String updateMemberByMemberId(MemberCriteria criteria) throws Exception {
		MemberTO to = memberMapper.getMemberInfo(criteria);
		List<NameValuePair> formparams=new ArrayList<NameValuePair>();
		formparams.add(new BasicNameValuePair("sourceType", "2"));
		formparams.add(new BasicNameValuePair("HQId", to.getHqId()));
		formparams.add(new BasicNameValuePair("memberId", to.getMemberId()));
		formparams.add(new BasicNameValuePair("memberName", to.getMemberName()));
		if(StringUtils.isNotBlank(criteria.getHqMemberGradeName())){
			formparams.add(new BasicNameValuePair("gradeId", String.valueOf(criteria.getHqMemberGradeId())));
			formparams.add(new BasicNameValuePair("gradeName", criteria.getHqMemberGradeName()));
		}else{
			formparams.add(new BasicNameValuePair("gradeId", String.valueOf(to.getHqMemberGradeId())));
			formparams.add(new BasicNameValuePair("gradeName", to.getHqMemberGradeName()));
		}
		formparams.add(new BasicNameValuePair("isCheckFuellingPw", String.valueOf(to.getIsCheck())));
		formparams.add(new BasicNameValuePair("fuellingPw", "******"));
		formparams.add(new BasicNameValuePair("licensePlate", to.getLicensePlate()));
		formparams.add(new BasicNameValuePair("isCheckLicensePlate", String.valueOf(to.getIsCheckLicensePlate())));
		formparams.add(new BasicNameValuePair("cardNo", to.getCardNo()));
		if(StringUtils.isNotBlank(criteria.getPhoneNum())){
			formparams.add(new BasicNameValuePair("phoneNum", criteria.getPhoneNum()));
		}else{
			formparams.add(new BasicNameValuePair("phoneNum", to.getPhoneNum()));
		}
		formparams.add(new BasicNameValuePair("idCard", to.getIdCard()));
		if(to.getBirthDay() != null){
			formparams.add(new BasicNameValuePair("birthday", to.getBirthDay()));
		}
		formparams.add(new BasicNameValuePair("status", String.valueOf(to.getStatus())));
		//修改油品
		if(criteria.getPrConfigList() != null){
			for(PRConfigTO configTO:criteria.getPrConfigList()){
				configTO.setPRId(configTO.getPrId());
				configTO.setPRName(configTO.getPrName());
				configTO.setPRStandard(configTO.getPrStandard());
			}
			formparams.add(new BasicNameValuePair("PRPermissionJson",gson.toJson(criteria.getPrConfigList())));
		}
		
		String result = httpManager.getHttpResponseByPost(CLOUD_REMOTE_CRM, CLOUD_ADD_MEMBER_EDIT, formparams);
//		ResultTO resultTO = gson.fromJson(result, new TypeToken<ResultTO>(){}.getType());
		log.info(to.getMemberId()+" will updateMember,result="+result);
//		if(resultTO.getCode() == 0){
//			return RESPONSE_CODE_OK;
//		}else{
			return result;
//		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.DEFAULT)
	public String getMemberAccountHistroyList(AccountAmountHistoryCriteria criteria) {
		List<AccountAmountHistoryTO> list = memberMapper.getMemberAccountHistroyList(criteria);
		PageTO page = new PageTO();
		page.setPageNo(criteria.getPageNo());
		page.setPageSize(criteria.getPageSize());
		if(criteria.getPageSize()!=null){
			int total = memberMapper.getCntMemberAccountHistroy(criteria);
			page.setPageCount(totalPage(total,criteria.getPageSize()));
			page.setTotal(total);
		}
		page.setDataList(list);
		return returnResult(CODE_OK, STRING_OK, page);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.DEFAULT)
	public String getMemberPointHistroyList(AccountPointHistoryCriteria criteria) {
		List<AccountPointHistoryTO> list = memberMapper.getMemberPointHistroyList(criteria);
		PageTO page = new PageTO();
		page.setPageNo(criteria.getPageNo());
		page.setPageSize(criteria.getPageSize());
		if(criteria.getPageSize()!=null){
			int total = memberMapper.getCntMemberPointHistroy(criteria);
			page.setPageCount(totalPage(total,criteria.getPageSize()));
			page.setTotal(total);
		}
		page.setDataList(list);
		return returnResult(CODE_OK, STRING_OK, page);
	}

	@Override
	public String chargeAmountByClient(AccountChargeHistoryCriteria chargeCriteria) throws Exception {
		final AccountChargeHistoryTO to = accountService.chargeAmountByClient(chargeCriteria);
		if(to == null){
			return RESPONSE_CODE_INVALID_PERMISSION;
		}
		threadPool.execute(new Thread(){
			public void run(){
				wxManager.chargeMessage(to);
				smsManager.chargeMessage(to);
			}
		});
		return returnResult(CODE_OK, STRING_OK, to);
	}
	
	@Override
	public String chargeAmountByWx(String hqId, String openId, Integer chargeAmount,
			String refId) throws Exception {
		final AccountChargeHistoryTO to = accountService.chargeAmountByWx(hqId, openId, 
				DecimalUtil.div(chargeAmount, 100.00, 2),refId);
		if(to == null){
			return RESPONSE_CODE_INVALID_MEMBER;
		}
		log.info("send chargeAmountByWx~~~~message");
		threadPool.execute(new Thread(){
			public void run(){
				wxManager.chargeMessage(to);
				smsManager.chargeMessage(to);
			}
		});
		return returnResult(CODE_OK, STRING_OK, to);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.DEFAULT)
	public String getMemberChargeHistroyList(AccountChargeHistoryCriteria criteria) {
		List<AccountChargeHistoryTO> list = memberMapper.getMemberChargeHistroyList(criteria);
		PageTO page = new PageTO();
		page.setPageNo(criteria.getPageNo());
		page.setPageSize(criteria.getPageSize());
		if(criteria.getPageSize()!=null){
			int total = memberMapper.getCntMemberChargeHistroy(criteria);
			page.setPageCount(totalPage(total,criteria.getPageSize()));
			page.setTotal(total);
		}
		page.setDataList(list);
		return returnResult(CODE_OK, STRING_OK, page);
	}

	@Override
	public String updateIsMemberPassword(MemberCriteria criteria) {
		int result = memberMapper.updateIsMemberPassword(criteria);
		if(result>0){
			return RESPONSE_CODE_OK;
		}
		return RESPONSE_CODE_SERVER_ERROR;
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.DEFAULT)
	public String editMemberPassword(MemberCriteria criteria) throws Exception{
		int cnt = memberMapper.getCntMemberPassword(criteria);
		criteria.setFuellingPassword(MD5.crypt(criteria.getMemberId()+criteria.getFuellingPassword()));
		if(cnt == 0){
			memberMapper.insertMemberPassword(criteria);
			return RESPONSE_CODE_OK;
		}else{
			memberMapper.editMemberPassword(criteria);
			return RESPONSE_CODE_OK;
		}
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.DEFAULT)
	public String resetMemberPassword(MemberCriteria criteria) {
		int cnt = memberMapper.getCntMemberPassword(criteria);
		criteria.setFuellingPassword(MD5.crypt(criteria.getMemberId()+criteria.getFuellingPassword()));
		if(cnt == 0){
			memberMapper.insertMemberPassword(criteria);
			return RESPONSE_CODE_OK;
		}else{
			memberMapper.resetMemberPassword(criteria);
			return RESPONSE_CODE_OK;
		}
	}

	@Override
	public String addMember(MemberCriteria criteria) throws Exception {
		List<NameValuePair> formparams=new ArrayList<NameValuePair>();
		formparams.add(new BasicNameValuePair("HQId", criteria.getHqId()));
		formparams.add(new BasicNameValuePair("HQName", criteria.getHqName()));
		formparams.add(new BasicNameValuePair("stationId", criteria.getStationId()));
		formparams.add(new BasicNameValuePair("stationName", criteria.getStationName()));
		formparams.add(new BasicNameValuePair("stationAdminId", criteria.getStationAdminId()));
		formparams.add(new BasicNameValuePair("stationAdminName", criteria.getStationAdminName()));
		formparams.add(new BasicNameValuePair("memberName", criteria.getMemberName()));
		formparams.add(new BasicNameValuePair("gradeId", String.valueOf(criteria.getHqMemberGradeId())));
		formparams.add(new BasicNameValuePair("gradeName", criteria.getHqMemberGradeName()));
		formparams.add(new BasicNameValuePair("isCheckFuellingPw", String.valueOf(criteria.getIsCheck())));
		formparams.add(new BasicNameValuePair("fuellingPw", criteria.getFuellingPassword()));
		formparams.add(new BasicNameValuePair("licensePlate", criteria.getLicensePlate()));
		formparams.add(new BasicNameValuePair("isCheckLicensePlate", String.valueOf(criteria.getIsCheckLicensePlate())));
		formparams.add(new BasicNameValuePair("cardNo", criteria.getCardNo()));
		formparams.add(new BasicNameValuePair("phoneNum", criteria.getPhoneNum()));
		formparams.add(new BasicNameValuePair("idCard", criteria.getIdCard()));
		formparams.add(new BasicNameValuePair("memo", criteria.getMemo()));
		formparams.add(new BasicNameValuePair("sourceType", "2"));
		String result = httpManager.getHttpResponseByPost(CLOUD_REMOTE_CRM, CLOUD_ADD_MEMBER_URI, formparams);
		log.info(criteria.getStationId()+" has addMember,result="+result);
		ResultTO resultTO = gson.fromJson(result, new TypeToken<ResultTO>(){}.getType());
		if(resultTO.getCode() == 0){
			MemberTO memberTO=new MemberTO();
			memberTO.setMemberId(resultTO.getData());
			return returnResult(CODE_OK,STRING_OK,memberTO);
		}else{
			log.error("addMember error because remote , result="+result);
			return result;
		}
	}

	@Override
	public String updateMemberStatus(MemberCriteria criteria) throws Exception {
		List<NameValuePair> formparams=new ArrayList<NameValuePair>();
		formparams.add(new BasicNameValuePair("HQId", criteria.getHqId()));
		formparams.add(new BasicNameValuePair("stationAdminId", criteria.getStationAdminId()));
		formparams.add(new BasicNameValuePair("memberId", criteria.getMemberId()));
		String result = null;
		if(criteria.getStatus() == MemberStatusType.NORMAL.getId()){
			result = httpManager.getHttpResponseByPost(CLOUD_REMOTE_CRM, CLOUD_ADD_MEMBER_UNFROZEN, formparams);
		}else if(criteria.getStatus() == MemberStatusType.FROZEN.getId()){
			result = httpManager.getHttpResponseByPost(CLOUD_REMOTE_CRM, CLOUD_ADD_MEMBER_FROZEN, formparams);
		}
		ResultTO resultTO = gson.fromJson(result, new TypeToken<ResultTO>(){}.getType());
		if(resultTO.getCode() == 0){
			return RESPONSE_CODE_OK;
		}
		log.error("updateMemberStatus error because remote , result="+result);
		return RESPONSE_CODE_SERVER_ERROR;
	}

	@Override
	public String changeCard(MemberCriteria criteria) throws Exception {
		List<NameValuePair> formparams=new ArrayList<NameValuePair>();
		formparams.add(new BasicNameValuePair("HQId", criteria.getHqId()));
		formparams.add(new BasicNameValuePair("cardNo", criteria.getCardNo()));
		formparams.add(new BasicNameValuePair("memberId", criteria.getMemberId()));
//		formparams.add(new BasicNameValuePair("phyCardNo", criteria.getPhyCardNo()));
//		formparams.add(new BasicNameValuePair("verificationCode", criteria.getVerificationCode()));
		String result = httpManager.getHttpResponseByPost(CLOUD_REMOTE_CRM, CLOUD_ADD_MEMBER_CHANGE_CARD, formparams);
		log.info(criteria.getMemberId()+" changeCard , result="+result);
		return result;
	}
	
	public String bindMemberOpenId(MemberCriteria criteria){
		if(StringUtils.isBlank(criteria.getCardNo())){
			return RESPONSE_CODE_INVALID_MEMBER;
		}
		MemberTO to = memberMapper.getMemberInfo(criteria);
		if(to == null){
			return RESPONSE_CODE_INVALID_MEMBER;
		}
		if(StringUtils.isNotBlank(to.getOpenId())){
			return RESPONSE_CODE_WX_BAND;
		}
		if(to.getCompanyType() == CompanyType.GENERAL_PAY.getId()){
			return RESPONSE_CODE_WX_BAND_COMPANY_ERROR;
		}
		
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		String ourl = "https://open.weixin.qq.com/connect/oauth2/authorize?"
				+ "appid=wx5d7213f7ae8e6fdf&"
				+ "redirect_uri=http%3A%2F%2Fwx.wiz-tech.com.cn%2Fmember%2Fbind%3FmemberId%3d|memberId|%26time%3d|time|%26hqId%3d|hqId|"
				+ "&response_type=code&scope=snsapi_base&state=123#wechat_redirect";
		String longUrl = ourl.replace("|memberId|", String.valueOf(to.getMemberId()))
				.replace("|time|", String.valueOf(System.currentTimeMillis()))
				.replace("|hqId|", criteria.getHqId());
		String shortUrl = wxRemoteManager.getShortUrl(longUrl);
		if(StringUtils.isNotBlank(shortUrl)){
			try {
				BufferedImage bi = QRCodeUtil.drawQRCode(shortUrl);
				ImageIO.write(bi, "jpg",baos);
				byte[] bytes = baos.toByteArray();
				ResultTO resultTO = new ResultTO();
				resultTO.setCode(CODE_OK);
				resultTO.setMsg(STRING_OK);
				resultTO.setData(ByteUtil.Bytes2HexString(bytes));
				return gson.toJson(resultTO);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return RESPONSE_CODE_SERVER_ERROR;
	}

	@Override
	public String updateFuellingStations(MemberCriteria criteria) throws Exception {
		int result = memberMapper.updateFuellingStations(criteria);
		if(result>0){
			return RESPONSE_CODE_OK;
		}
		return RESPONSE_CODE_SERVER_ERROR;
	}

	@Override
	public String updateChargeStations(MemberCriteria criteria) throws Exception {
		int result = memberMapper.updateChargeStations(criteria);
		if(result>0){
			return RESPONSE_CODE_OK;
		}
		return RESPONSE_CODE_SERVER_ERROR;
	}

}
